﻿/*
 * statusmgr.cpp
 *
 *  Created on: 2017年3月27日
 *      Author: work
 */

#include <dm/export.hpp>

#define DM_API_SCADA DM_API_EXPORT

#include <dm/scada/statusmgr.hpp>

#include <dm/scada/eventmgr.hpp>
#include <dm/scada/scadainfo.hpp>
#include <dm/scada/devicemgr.hpp>
#include <dm/os/log/logger.hpp>

#include <dm/datetime.hpp>

namespace dm{
namespace scada{

static const char* logModule = "CStatusMgr.scada.dm";

CStatusMgr::CStatusMgr( CScada& scada ):CScada(scada),
		m_cfg(scada.statusInfos(),scada.info()->statusCount()){
}

CStatusMgr& CStatusMgr::ins(){
	static CStatusMgr i(CScada::ins());
	return i;
}

/**
 * 设置描述
 * @param idx
 * @param str
 * @return
 */
bool CStatusMgr::setDesc( const index_t& idx,const char* str ){
	SStatusInfo* p = m_cfg.at(idx);
	if( p ){
		p->desc = str;
		return true;
	}else
		return false;
}

index_t CStatusMgr::indexOfRt( const rt_t* value )const{
	if( value<statuses() || value>statuses()+size() )
		return Idx_Inv;
	return value - statuses();
}

index_t CStatusMgr::indexOfRt( const volatile rt_t* value )const{
	if( value<statuses() || value>statuses()+size() )
		return Idx_Inv;
	return value - statuses();
}

/**
 * 设置级别
 * @param idx
 * @param level
 * @return
 */
bool CStatusMgr::setLevel( const index_t& idx,const SStatusInfo::ELevel& level ){
	SStatusInfo* p = m_cfg.at(idx);
	if( p ){
		p->level = level;
		return true;
	}else
		return false;
}

/**
 * 设置存盘标志
 * @param idx
 * @param s
 * @return
 */
bool CStatusMgr::setFlagSave( const index_t& idx,bool s ){
	SStatusInfo* p = m_cfg.at(idx);
	if( p ){
		p->setFlagSave(s);
		return true;
	}else
		return false;
}

/**
 * 设置产生时标数据标志
 * @param idx
 * @param s
 * @return
 */
bool CStatusMgr::setFlagGenTimed( const index_t& idx,bool s ){
	SStatusInfo* p = m_cfg.at(idx);
	if( p ){
		p->setFlagGenTimed(s);
		return true;
	}else
		return false;
}

/**
 * 设置上报时标数据标志
 * @param idx
 * @param s
 * @return
 */
bool CStatusMgr::setFlagReportTimed( const index_t& idx,bool s ){
	SStatusInfo* p = m_cfg.at(idx);
	if( p ){
		p->setFlagReportTimed(s);
		return true;
	}else
		return false;
}

const char* CStatusMgr::valueDesc( const index_t& idx,const CStatus::value_t& value )const{
	switch( value ){
	case CStatus::InvOff:
		return invOffDesc(idx);
		break;
	case CStatus::Off:
		return offDesc(idx);
		break;
	case CStatus::On:
		return onDesc(idx);
		break;
	case CStatus::InvOn:
		return invOnDesc(idx);
	default:
		return "未定义状态";
	}
}

index_t CStatusMgr::deviceIndex( const index_t& idx )const{
	if( idx<0 || idx>=size() )
		return Idx_Inv;
	CDeviceMgr& d = CDeviceMgr::ins();

	for( index_t i=0;i<d.size();++i ){
		if( d.info(i)->posOfStatus<=idx &&
				(d.info(i)->posOfStatus+d.info(i)->sizeOfStatus)>idx )
			return i;
	}

	return Idx_Inv;
}

const char* CStatusMgr::deviceDesc( const index_t& idx )const{
	if( idx<0 || idx>=size() )
		return NULL;
	CDeviceMgr& d = CDeviceMgr::ins();

	for( index_t i=0;i<d.size();++i ){
		if( d.info(i)->posOfStatus<=idx &&
				(d.info(i)->posOfStatus+d.info(i)->sizeOfStatus)>idx )
			return d.info(i)->desc.c_str();
	}

	return NULL;
}

const char* CStatusMgr::rtDesc( const index_t& idx ){
	return valueDesc(idx,rtValue(idx));
}

bool CStatusMgr::update( const index_t& idx,const CStatus& value,const EDataSource& ds,const dm::CTimeStamp& ts ){
	if( idx<0 || idx>=size() ){
		log().warnning(THISMODULE "状态量索引溢出%d",idx);
		return false;
	}

	if( statuses()[idx].update(value,ds,ts) && info(idx)->isFlagGenTimed() ){
		CEvent e(CEvent::Status,idx,ts);
		e.value.status = value.getValue();
		CEventMgr::ins().gen(e);
	}

	return true;
}

bool CStatusMgr::set( const index_t& idx,const CStatus& value,const EDataSource& ds,const dm::CTimeStamp& ts ){
	if( idx<0 || idx>=size() ){
		log().warnning(THISMODULE "状态量索引溢出%d",idx);
		return false;
	}

	statuses()[idx].update(value,ds,ts);

	return true;
}

bool CStatusMgr::gen( const index_t& idx,const CStatus& value,const dm::CTimeStamp& ts ){
	if( idx<0 || idx>=size() ){
		log().warnning(THISMODULE "状态量索引溢出%d",idx);
		return false;
	}

	CEvent e(CEvent::Status,idx,ts);
	e.value.status = value.getValue();
	CEventMgr::ins().gen(e);

	return true;
}

void CStatusMgr::printInfo( const index_t& idx,std::ostream& ostr )const{
	const SStatusInfo* p = info(idx);
	if( p ){
		ostr <<"ID:"<<p->id
				<<" 名字:"<<p->name.c_str()
				<<" 描述:"<<p->desc.c_str()
				<<" 分状态:"<<CStatusDescMgr::ins().desc(p->desc_off)
				<<" 合状态:"<<CStatusDescMgr::ins().desc(p->desc_on)
				<<" 无效分状态:"<<CStatusDescMgr::ins().desc(p->desc_invOff)
				<<" 无效合状态:"<<CStatusDescMgr::ins().desc(p->desc_invOn)
				<<" 级别:"<<p->level
				<<" 存盘:";
		if( p->isFlagSave() )
			ostr <<"允许";
		else
			ostr <<"禁止";

		ostr <<" 产生时标数据:";
		if( p->isFlagGenTimed() )
			ostr <<"是";
		else
			ostr <<"否";

		ostr <<" 上报时标数据:";
		if( p->isFlagReportTimed() )
			ostr <<"是";
		else
			ostr <<"否";
	}else{
		ostr <<"无效索引("<<idx<<')';
	}
}

void CStatusMgr::printInfoValue( const index_t& idx,std::ostream& ostr ){
	const SStatusInfo* p = info(idx);
	if( p ){
		rt_t* pv = rt(idx);
		ostr <<"ID:"<<p->id
				<<" 名字:"<<p->name.c_str()
				<<" 描述:"<<p->desc.c_str()
				<<" 值:"<<(unsigned int)(pv->getValue().getValue())
				<<" 值描述:"<<valueDesc(idx,pv->getValue().getValue())
				<<" 数据方式:"<<pv->getDataSource()
				<<" 码值:"<<(unsigned int)(pv->getValue().getRaw())
				<<" 时标:"<< dm::CDateTime(pv->getTimeStamp()).toString().c_str();
	}else{
		ostr <<"无效索引("<<idx<<')';
	}
}

}
}


